package com.lib76.socket.model;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.lib76.socket.Constants;
import com.lib76.socket.model.protocol.SocketProtocolGroup;
import com.lib76.socket.model.protocol.SocketProtocolObject;
import com.lib76.socket.model.protocol.SocketProtocolParameter;

/**
 * 报文对象
 * @author 张浩
 * @version 1.0.0
 */
public abstract class SocketMessage {

	protected Object originalMessage;				//原始报文
	protected Object originalMessageBody;			//原始报文体
	protected SocketProtocolObject protocolObject;	//报文协议
	protected Map<String,Object> data;				//数据
	
	private boolean isAnalysisHeader = false;		//是否已解析报文头部
	private boolean isAnalysisBody = false;			//是否已解析报文体
	
	/**
	 * 是否包含报文协议
	 * @return
	 */
	public boolean hasProtocol(){
		if(this.protocolObject != null && this.protocolObject.getProtocol() != null){
			return true;
		}
		return false;
	}
	
	/**
	 * 解析报文头部
	 */
	private void analysisHeader(){
		if(isAnalysisHeader == false && hasProtocol()){
			if(Constants.MSG_PROTOCOL_TYPE_JSON.equals(this.getProtocolObject().getType())){
				
			}
		}
	}
	
	/**
	 * 解析报文体
	 */
	private void analysisBody(){
		if(isAnalysisBody == false && hasProtocol() && isAnalysisHeader){
			if(Constants.MSG_PROTOCOL_TYPE_JSON.equals(this.getProtocolObject().getType())){
				
			}
		}
	}
	
	//是否是原始报文输出
	protected boolean isOriginalMessageOutput = false;
	protected boolean readBody = false;	//是否已经读过报文体

	protected Integer length = 0; //长度

	public SocketMessage(){}
	
	public SocketMessage(SocketProtocolObject protocolObject){
		this.data = new HashMap<String,Object>();
		this.protocolObject = protocolObject;
	}
	
	public SocketMessage(Object originalMessage){
		this.originalMessage = originalMessage;
		this.data = new HashMap<String,Object>();
		readOriginalMessage(originalMessage);
	}
	
	public SocketMessage(SocketProtocolObject protocolObject,Object originalMessage){
		this.originalMessage = originalMessage; 
		this.data = new HashMap<String,Object>();
		this.protocolObject = protocolObject;
		readOriginalMessage(originalMessage);
		if(this.hasProtocol()){
			try {
				read(this.protocolObject.getHeaderProtocolParameter());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void writeOriginalMessage(Object message){
		this.originalMessage = message;
		this.isOriginalMessageOutput = true;
	}
	
	public void readBody(){
		if(this.hasProtocol() && !readBody){
			try {
				read(this.protocolObject.getBodyFields());
				readBody = true;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public String readString(String name){
		readBody();
		Object obj = this.data.get(name);
		if(obj != null){
			return obj.toString();
		}
		return null;
	}
	
	public Integer readInteger(String name){
		readBody();
		Object obj = this.data.get(name);
		if(obj != null){
			return Integer.valueOf(obj.toString());
		}
		return null;
	}
	
	public Float readFloat(String name){
		readBody();
		Object obj = this.data.get(name);
		if(obj != null){
			return Float.valueOf(obj.toString());
		}
		return null;
	}
	
	public void writeString(String name,String value){
		this.data.put(name, value);
	}
	
	public void writeInteger(String name,Integer value){
		this.data.put(name, value);
	}
	
	public void writeFloat(String name,Float value){
		this.data.put(name, value);
	}
	
	public Object output() throws Exception{
		if(isOriginalMessageOutput == true){
			return this.originalMessage;
		}
		if(this.hasProtocol()){
			this.data.put(SocketProtocolGroup.COMMAND_FIELD_NAME, this.protocolObject.getCommand());
			this.data.put(SocketProtocolGroup.DIRECTION_FIELD_NAME, this.protocolObject.getDirection());
			this.data.put(SocketProtocolGroup.BODY_LENGTH_FIELD_NAME, this.protocolObject.getBodyLength());
			this.data.put(SocketProtocolGroup.BODY_TYPE_FIELD_NAME, this.protocolObject.getBodyType());
		}
		return buildMessage();
	}

	public abstract void readOriginalMessage(Object originalMessage);
	
	public abstract Object buildMessage() throws Exception;
	
	public abstract void read(List<SocketProtocolParameter> parameters) throws Exception;
	
	public abstract void write(List<SocketProtocolParameter> parameters) throws Exception;
	
	public SocketProtocolObject getProtocolObject() {
		return protocolObject;
	}

	public void setProtocolObject(SocketProtocolObject protocolObject) {
		this.protocolObject = protocolObject;
	}
	
	@Override
	public String toString() {
		if(this.protocolObject != null){
			return data.toString();
		}else if(this.originalMessage != null){
			return this.originalMessage.toString();
		}
		return super.toString();
	}

	public Object getOriginalMessage() {
		return originalMessage;
	}
}
